#!/usr/bin/python
# -*- coding: UTF-8 -*-

import hashlib
import os
import queue
import time
import timeit
import sqlite3
import threading
import gevent
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler

disk = ['A:\\', 'B:\\', 'C:\\', 'D:\\', 'E:\\', 'F:\\', 'G:\\', 'H:\\', 'I:\\', 'J:\\', 'K:\\', 'L:\\', 'M:\\',
        'N:\\', 'O:\\', 'P:\\', 'Q:\\', 'R:\\', 'S:\\', 'T:\\', 'U:\\', 'V:\\', 'W:\\', 'X:\\', 'Y:\\', 'Z:\\']

conn = sqlite3.connect('index.db', check_same_thread=False)
c = conn.cursor()

queue = queue.Queue()

class Qs():
    def __init__(self, parent=None):
        # super(Qs, self).__init__(parent)
        pass

    # TODO 优化处理速度
    def loopDir(self, path):
        '''遍历盘符创建文件索引.
        每个盘符commit一次.
        '''
        datas = []
        hashvalue = hash('%s%s%s%d' % (path, path, '', 0))
        datas.append((path, path, '', 0, hashvalue))

        for dir, subdirs, files in os.walk(path):
            for subdir in subdirs:
                hashvalue = hash('%s%s%s%d' % (subdir, dir, '', 0))
                datas.append((subdir, dir, '', 0, hashvalue))
            for file in files:
                suffix = ''
                if '.' in file:
                    suffix = file.split('.')[-1]
                hashvalue = hash('%s%s%s%d' % (file, dir, suffix, 1))
                datas.append((file, dir, suffix, 1, hashvalue))
            c.executemany('INSERT INTO F VALUES(?,?,?,?,?)', datas)
            datas.clear()
            conn.commit()


    def run(self):
        '''初始化数据库、表.
        每次运行删除索引表，并重新创建.
        为提升数据库性能，修改了数据库的写入配置:
            1、开启了WAL:Write Ahead Logging.
            2、关闭了写同步synchronous.
        '''
        c.execute('PRAGMA journal_mode=WAL')
        c.execute('PRAGMA synchronous = OFF')
        conn.commit()

        c.execute("select name from sqlite_master where type='table' order by name")
        conn.commit()
        tables = c.fetchall()
        if len(tables) > 0 and 'F' in tables[0]:
            c.execute('DROP TABLE F')
            conn.commit()
        
        c.execute('''CREATE TABLE F(
                NAME CHAR(500),
                PATH CHAR(2000),
                SUFFIX CHAR(100),
                TYPE INT,
                HASH CHAR(100)
                )''')
        conn.commit()

        for d in disk:
            if os.path.isdir(d) == True:
                gevent.spawn(self.loopDir,d).join()

        gevent.spawn(self.watch).join()

    def watch(self):
        '''
        文件/目录 操作监控
        '''
        fch = FileChangeHandler()
        for d in disk:
            if os.path.isdir(d) == True:
                observer = Observer()
                observer.schedule(fch, d, recursive=True)
                observer.start()


class FileChangeHandler(FileSystemEventHandler):
    def on_any_event(self, event):
        if(event.event_type in 'deleted,created,moved'):
            queue.put(event)


# TODO 优化CPU消耗
class SqlRunner():
    def __init__(self, parent=None):
        pass

    def run(self):
        if queue.empty() != True:
            event = queue.get()
            if ('AppData\\Roaming\\Microsoft\\Windows\\Recent' not in event.src_path):
                    try:
                        print(event)
                        name = event.src_path.split('\\')[-1]
                        path = event.src_path.replace('\\%s' % name, '')
                        fileType = 0
                        if not event.is_directory:
                            fileType = 1
                        suffix = ''
                        if '.' in name:
                            suffix = name.split('.')[-1]

                        hashvalue = hash('%s%s' %
                                         (event.src_path, fileType))
                        c.execute(
                            'DELETE FROM F WHERE HASH=?', (hashvalue,))  # always delete
                        conn.commit()

                        if event.event_type == 'created':
                            c.execute("INSERT INTO F VALUES(?,?,?,?,?)",
                                      (name, path, suffix, fileType, hashvalue))
                        elif event.event_type == 'moved':
                            name_new = event.dest_path.split('\\')[-1]
                            path_new = event.dest_path.replace(
                                '\\%s' % name_new, '')
                            fileType = 0
                            if not event.is_directory:
                                fileType = 1
                            suffix = ''
                            if '.' in name_new:
                                suffix = name_new.split('.')[-1]

                            hashvalue = hash('%s%s' %
                                             (event.dest_path))
                            c.execute("INSERT INTO F VALUES(?,?,?,?,?)",
                                      (name_new, path_new, suffix, fileType, hashvalue))
                        conn.commit()
                    except BaseException as err:
                        print(err)

if __name__ == "__main__":
    qs = Qs()
    qs.run()
    r = SqlRunner()
    while 1:
        r.run()